<h1 id="custombehavior">Custom behavior</h1>

<p>This section summarizes Duktape behavior which deviates from the E5.1 or
other relevant specifications.</p>

<h2>Duktape built-in and custom types</h2>

<p>The <code>Duktape</code> built-in is (of course) non-standard and provides
access to Duktape specific features.  Also the buffer, pointer, and lightfunc
types are custom.</p>

<h2>Hidden Symbols</h2>

<p>Objects may have properties with <a href="#symbols">hidden Symbol</a> keys.
These are similar to ES2015 Symbols but won't be enumerated or returned from even
<code>Object.getOwnPropertySymbols()</code>.  Ordinary ECMAScript code cannot
refer to such properties because the keys intentionally use an invalid (extended)
UTF-8 representation.</p>

<h2>"use duk notail" directive</h2>

<p>The <a href="#use-duk-notail">"use duk notail"</a> directive is non-standard.
It prevents a function from being tail called.</p>

<h2>"const" treated mostly like "var"</h2>

<p>The <code>const</code> keyword is supported with minimal non-standard
semantics (officially defined in ECMAScript 6).  See
<a href="#es6-const">Const variables</a> for more detail.</p>

<h2>Additional Error and Function object properties</h2>

<p>See
<a href="#errorobjects">Error objects</a> and
<a href="functionobjects">Function objects</a>.</p>

<p>Non-strict function instances don't have a <code>caller</code> property in the
E5/E5.1 specification.  Some real world code expects to have this property, so it
can be enabled with the config option <code>DUK_USE_NONSTD_FUNC_CALLER_PROPERTY</code>.</p>

<h2>Function statements</h2>

<p>E5.1 does not allow a function declaration to appear outside program or
function top level:</p>
<pre class="ecmascript-code">
function test() {
    // point A
    try {
        throw new Error('test');
    } catch (e) {
        // This is a SyntaxError in E5.1
        function func() {
            print(typeof e);
        }
        // point B
    }
    // point C
}
</pre>

<p>These declarations are also referred to as "function statements", and appear
quite often in real world code (including the test262 test suite), so they are
allowed by Duktape.  Unfortunately there are several semantics used by different
Javascript engines (<a href="http://www.ecma-international.org/ecma-262/6.0/index.html#sec-block-level-function-declarations-web-legacy-compatibility-semantics">ES2015</a>
unfortunately doesn't specify semantics for function statements either).
Duktape follows the V8 behavior for function statements:</p>
<ul>
<li>Strict function: a SyntaxError is thrown (standard behavior).</li>
<li>Non-strict function: treat a function statement like an ordinary function
    declaration, conceptually "hoisting" it to the top of the function.</li>
</ul>

<p>As an illustration, the above example would behave as the following:</p>
<pre class="ecmascript-code">
function test() {
    function func() {
        print(typeof e);
    }
 
    try {
        throw new Error('test');
    } catch (e) {
    }
}
</pre>

<p><code>func()</code> in the above example would already be declared
and callable in point A, and would not have access to the <code>e</code>
binding in any of the points A, B, or C.</p>

<h2>RegExp leniency</h2>

<p>Most ECMAScript engines support more syntax than guaranteed by the
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-15.10.1">ECMAScript
E5.1 specification (Section 15.10.1 Patterns)</a>.  As a result there's quite
a lot of code that won't work with strict ECMAScript E5.1 regexp syntax.  Much
of the additional syntax expected of web browser engines is documented in
<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns">ES2015 Annex B.1.4 Regular Expression Patterns</a>.
However, note that features in
<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-additional-ecmascript-features-for-web-browsers">Annex B Additional ECMAScript Features for Web Browsers</a> are
not recommended for new code:
"These features are not considered part of the core ECMAScript language.
Programmers should not use or assume the existence of these features and
behaviours when writing new ECMAScript code. ECMAScript implementations
are discouraged from implementing these features unless the implementation
is part of a web browser or is required to run the same legacy ECMAScript
code that web browsers encounter."</p>

<p>Duktape also allows some ES2015 Annex B syntax to better support existing
code.  You can turn this non-standard behavior off using config options if
you prefer.  Some examples of additional syntax supported:</p>

<pre>
  /{(\d+)}/    // unescaped left curly, digits, unescaped right curly; ES2015 Annex B
  /\{(\d+)\}/  // same, ES5 compliant

  /]/          // unescaped right bracket; ES2015 Annex B
  /\]/         // same, ES5 compliant

  /\$/         // literal dollar using escape; ES2015 Annex B
  /\u0024/     // same, ES5 compliant
</pre>

<h2>Setter/getter key argument</h2>

<p>ECMAScript standard behavior is that setters and getters are not given
the name of the property being accessed.  This prevents reusing a single
setter or a getter for multiple properties; separate functions are needed
for each property which is sometimes inconvenient and wastes memory.</p>

<p>Duktape provides the property key name as a non-standard additional
argument to setter and getter functions.  See
<a href="https://github.com/svaarala/duktape/blob/master/tests/ecmascript/test-dev-nonstd-setget-key-argument.js">test-dev-nonstd-setget-key-argument.js</a>
and <a href="#propertyvirtualization">Property virtualization</a>
for more discussion.  The strict standards compliant behavior can be enabled
by disabling the config options <code>DUK_USE_NONSTD_GETTER_KEY_ARGUMENT</code>
and <code>DUK_USE_NONSTD_SETTER_KEY_ARGUMENT</code>.</p>

<h2>Object.setPrototypeOf and Object.prototype.__proto__ (ES2015)</h2>

<p>See <a href="#es6-proto">Object.setPrototypeOf and Object.prototype.__proto__</a>.</p>

<h2>Proxy object (ES2015)</h2>

<p>See <a href="#es6-proxy">Proxy object (subset)</a>.</p>

<h2>JSON.stringify() escapes U+2028 and U+2029</h2>

<p><code>JSON.stringify()</code> standard behavior is to output U+2028 and
U+2029 without escaping.  This leads to counterintuitive behavior when the
output is used in a web page or parsed with <code>eval()</code>: the U+2028
and U+2029 characters are considered line terminators which leads to a syntax
error (unterminated string).  Duktape escapes U+2028 and U+2029 by default
to avoid this issue; you can turn on the compliant behavior by disabling the
config option <code>DUK_USE_NONSTD_JSON_ESC_U2028_U2029</code>.</p>

<h2>Array instance numeric index writes</h2>

<p>By default Duktape provides a fast path for writing to Array instances.
The fast path is active when numeric indices are used (e.g. <code>arr[7] = 'foo'</code>)
and a few internal conditions are met.  When the fast path is taken, Duktape
doesn't check Array.prototype for conflicting properties (these are very rare in
practical code), which makes common array writes faster.  The behavior is
non-compliant, but there's no outward difference unless Array.prototype has
properties with numeric keys.  You can turn on the compliant behavior by
disaling the config options <code>DUK_USE_NONSTD_ARRAY_WRITE</code> and
<code>DUK_USE_ARRAY_PROP_FASTPATH</code>.  See the following for more
details on the fast path behavior:
<a href="https://github.com/svaarala/duktape/blob/master/tests/ecmascript/test-misc-array-fast-write.js">test-misc-array-fast-write.js</a>.</p>

<h2 id="typedarray-custombehavior">TypedArray binding</h2>

<p>The plain buffer custom type behaves mostly like an Uint8Array object
for ECMAScript code, but has a separate type in the Duktape C API.</p>

<h2 id="nodejsbuffer-custombehavior">Node.js Buffer binding</h2>

<p>Duktape provides a Node.js-like <code>Buffer</code> binding.  There are
some differences between the Node.js behavior and Duktape behavior.  These
differences include:</p>
<ul>
<li>Interoperability with other buffer types: ArrayBuffer, DataView, or a
    typed array (Uint8Array etc) is usually allowed wherever a Node.js Buffer
    would be allowed.</li>
<li>Buffer data is always zeroed on allocation and when concatenation
    <code>totalLength</code> exceeds combined size of input buffers.</li>
<li>Read/write offset and length arguments are always validated to ensure
    memory safe behavior, even when <code>noAssert</code> is true.  Failed
    reads return NaN and failed writes return 0.</li>
<li>Partial read/writes are never done: if a read/write is partially
    outside the valid buffer, it is rejected.</li>
<li>Small differences in argument coercion for e.g. offset and length
    values.</li>
<li>Write calls coerce their value argument like TypedArray, e.g. when
    writing 0x100 using <code>writeUInt8()</code> silently coerces to
    0x00 rather than throwing a TypeError.</li>
<li>Duktape only supports the <code>"utf8"</code> encoding (and accepts no
    spelling variants).  Most API calls ignore an encoding argument, and
    use UTF-8 implicitly for string-to-buffer coercion.</li>
<li>UTF-8 decoding replacement character approach follows
    <a href="http://unicode.org/review/pr-121.html">Unicode Technical Committee Recommended Practice for Replacement Characters</a>
    which matches WHATWG Encoding API specification but differs from Node.js
    (at least up to version v6.9.1).</li>
</ul>

<h2>Shebang comment support</h2>

<p><code>duk_compile()</code> flag <code>DUK_COMPILE_SHEBANG</code> allows shebang
comment parsing: <code>#!</code> on the first column of the first line causes the
line to be treated as a comment.  For example:</p>
<pre>
#!/usr/bin/duk
print('Hello world!');
</pre>

<p>The feature can be disabled by undefining <code>DUK_USE_SHEBANG_COMMENTS</code>.</p>
